#!/usr/bin/env python
import re
import string
import logging

class Style(object):
    logger = logging.getLogger('canvaside.canvas.style')

    @staticmethod
    def create(sheet):
        styles = []

        for name in sheet.style.keys():
            if CANVAS_STYLES.has_key(name):
                styles.append(CANVAS_STYLES[name](sheet.style.getProperty(name).value))
            else:
                Style.logger.warn("unsupport style: %s", name)

        return styles

class Border(Style):
    RE_PX = re.compile("(?P<width>\d+)px")

    def __init__(self, style):
        self.width, self.style, self.color = style.split()

    @property
    def linewidth(self):
        m = self.RE_PX.match(self.width)

        if m:
            return int(m.group('width'))

        self.logger.warn("unsupport border-width value: %s", self.width)

        return 1

    def apply(self, canvas, x, y, w, h):
        if self.style != 'solid':
            self.logger.warn("unsupport border-style value: %s", self.style)

        canvas.strokeStyle = self.color

        for i in range(self.linewidth):
            canvas.strokeRect(x+i, y+i, x+w-1-i, y+h-1-i)

CANVAS_STYLES = {
    'border' : Border,
}

def create(sheet):
    return Style.create(sheet)

def formatColor(rgba):
    for name, value in COLOR_MAPS.items():
        if value == rgba:
            return name

    r, g, b, a = rgba

    if a == 255:
        return "#%02x%02x%02x" % (r, g, b)
    else:
        return "rgba(%d, %d, %d, 0.%d)" % (r, g, b, a * 100000 / 255)

def parseColor(color):
    rgb = COLOR_MAPS.get(color, COLOR_MAPS.get(string.lower(color), None))

    if rgb:
        if not isinstance(rgb, type(())):
            COLOR_MAPS[color] = rgb = parseColor(rgb)

        return rgb

    m = re.match("#(?P<red>\w)(?P<green>\w)(?P<blue>\w)$", color)

    if m:
        return (int(m.group('red')*2, 16),
                int(m.group('green')*2, 16),
                int(m.group('blue')*2, 16), 255)

    m = re.match("#(?P<red>\w{2})(?P<green>\w{2})(?P<blue>\w{2})$", color)

    if m:
        return (int(m.group('red'), 16),
                int(m.group('green'), 16),
                int(m.group('blue'), 16), 255)

    def ensureInRange(value, maxv=255, minv=0):
        return max(min(int(value), maxv), minv)

    def parsePercent(value):
        return max(min(float(value), 100.0), 0.0) / 100

    def toRGB(value):
        return int(value * 255 + 0.5)

    m = re.match("rgb\(\s*(?P<red>-?\d+)\s*,\s*(?P<green>-?\d+)\s*,\s*(?P<blue>-?\d+)\s*\)$", color)

    if m:
        return (ensureInRange(m.group('red')),
                ensureInRange(m.group('green')),
                ensureInRange(m.group('blue')), 255)

    m = re.match("rgba\(\s*(?P<red>-?\d+)\s*,\s*(?P<green>-?\d+)\s*,\s*(?P<blue>-?\d+)\s*,\s*(?P<alpha>-?[\d\.]+)\s*\)$", color)

    if m:
        return (ensureInRange(m.group('red')),
                ensureInRange(m.group('green')),
                ensureInRange(m.group('blue')),
                ensureInRange(toRGB(float(m.group('alpha')))))

    m = re.match("rgb\(\s*(?P<red>-?\d+)%\s*,\s*(?P<green>-?\d+)%\s*,\s*(?P<blue>-?\d+)%\s*\)$", color)

    if m:
        return (toRGB(parsePercent(m.group('red'))),
                toRGB(parsePercent(m.group('green'))),
                toRGB(parsePercent(m.group('blue'))), 255)

    m = re.match("rgba\(\s*(?P<red>-?\d+)%\s*,\s*(?P<green>-?\d+)%\s*,\s*(?P<blue>-?\d+)%\s*,\s*(?P<alpha>-?[\d\.]+)\s*\)$", color)

    if m:
        return (toRGB(parsePercent(m.group('red'))),
                toRGB(parsePercent(m.group('green'))),
                toRGB(parsePercent(m.group('blue'))),
                ensureInRange(toRGB(float(m.group('alpha')))))

    m = re.match("hsl\(\s*(?P<hue>-?\d+)\s*,\s*(?P<saturation>-?\d+)%\s*,\s*(?P<lightness>-?\d+)%\s*\)$", color)

    if m:
        from colorsys import hls_to_rgb

        r, g, b = hls_to_rgb(ensureInRange(m.group('hue'), 360) / 360.0,
                             parsePercent(m.group('lightness')),
                             parsePercent(m.group('saturation')))

        return (toRGB(r), toRGB(g), toRGB(b), 255)

    m = re.match("hsla\(\s*(?P<hue>-?\d+)\s*,\s*(?P<saturation>-?\d+)%\s*,\s*(?P<lightness>-?\d+)%\s*,\s*(?P<alpha>-?[\d\.]+)\s*\)$", color)

    if m:
        from colorsys import hls_to_rgb

        r, g, b = hls_to_rgb(ensureInRange(m.group('hue'), 360) / 360.0,
                             parsePercent(m.group('lightness')),
                             parsePercent(m.group('saturation')))

        return (toRGB(r), toRGB(g), toRGB(b), ensureInRange(toRGB(float(m.group('alpha')))))

COLOR_MAPS =  {
    'transparent': (0, 0, 0, 0),
    'aliceblue': '#f0f8ff',
    'antiquewhite': '#faebd7',
    'aqua': '#00ffff',
    'aquamarine': '#7fffd4',
    'azure': '#f0ffff',
    'beige': '#f5f5dc',
    'bisque': '#ffe4c4',
    'black': '#000000',
    'blanchedalmond': '#ffebcd',
    'blue': '#0000ff',
    'blueviolet': '#8a2be2',
    'brown': '#a52a2a',
    'burlywood': '#deb887',
    'cadetblue': '#5f9ea0',
    'chartreuse': '#7fff00',
    'chocolate': '#d2691e',
    'coral': '#ff7f50',
    'cornflowerblue': '#6495ed',
    'cornsilk': '#fff8dc',
    'crimson': '#dc143c',
    'cyan': '#00ffff',
    'darkblue': '#00008b',
    'darkcyan': '#008b8b',
    'darkgoldenrod': '#b8860b',
    'darkgray': '#a9a9a9',
    'darkgrey': '#a9a9a9',
    'darkgreen': '#006400',
    'darkkhaki': '#bdb76b',
    'darkmagenta': '#8b008b',
    'darkolivegreen': '#556b2f',
    'darkorange': '#ff8c00',
    'darkorchid': '#9932cc',
    'darkred': '#8b0000',
    'darksalmon': '#e9967a',
    'darkseagreen': '#8fbc8f',
    'darkslateblue': '#483d8b',
    'darkslategray': '#2f4f4f',
    'darkslategrey': '#2f4f4f',
    'darkturquoise': '#00ced1',
    'darkviolet': '#9400d3',
    'deeppink': '#ff1493',
    'deepskyblue': '#00bfff',
    'dimgray': '#696969',
    'dimgrey': '#696969',
    'dodgerblue': '#1e90ff',
    'firebrick': '#b22222',
    'floralwhite': '#fffaf0',
    'forestgreen': '#228b22',
    'fuchsia': '#ff00ff',
    'gainsboro': '#dcdcdc',
    'ghostwhite': '#f8f8ff',
    'gold': '#ffd700',
    'goldenrod': '#daa520',
    'gray': '#808080',
    'grey': '#808080',
    'green': '#008000',
    'greenyellow': '#adff2f',
    'honeydew': '#f0fff0',
    'hotpink': '#ff69b4',
    'indianred': '#cd5c5c',
    'indigo': '#4b0082',
    'ivory': '#fffff0',
    'khaki': '#f0e68c',
    'lavender': '#e6e6fa',
    'lavenderblush': '#fff0f5',
    'lawngreen': '#7cfc00',
    'lemonchiffon': '#fffacd',
    'lightblue': '#add8e6',
    'lightcoral': '#f08080',
    'lightcyan': '#e0ffff',
    'lightgoldenrodyellow': '#fafad2',
    'lightgray': '#d3d3d3',
    'lightgrey': '#d3d3d3',
    'lightgreen': '#90ee90',
    'lightpink': '#ffb6c1',
    'lightsalmon': '#ffa07a',
    'lightseagreen': '#20b2aa',
    'lightskyblue': '#87cefa',
    'lightslategray': '#778899',
    'lightslategrey': '#778899',
    'lightsteelblue': '#b0c4de',
    'lightyellow': '#ffffe0',
    'lime': '#00ff00',
    'limegreen': '#32cd32',
    'linen': '#faf0e6',
    'magenta': '#ff00ff',
    'maroon': '#800000',
    'mediumaquamarine': '#66cdaa',
    'mediumblue': '#0000cd',
    'mediumorchid': '#ba55d3',
    'mediumpurple': '#9370d8',
    'mediumseagreen': '#3cb371',
    'mediumslateblue': '#7b68ee',
    'mediumspringgreen': '#00fa9a',
    'mediumturquoise': '#48d1cc',
    'mediumvioletred': '#c71585',
    'midnightblue': '#191970',
    'mintcream': '#f5fffa',
    'mistyrose': '#ffe4e1',
    'moccasin': '#ffe4b5',
    'navajowhite': '#ffdead',
    'navy': '#000080',
    'oldlace': '#fdf5e6',
    'olive': '#808000',
    'olivedrab': '#6b8e23',
    'orange': '#ffa500',
    'orangered': '#ff4500',
    'orchid': '#da70d6',
    'palegoldenrod': '#eee8aa',
    'palegreen': '#98fb98',
    'paleturquoise': '#afeeee',
    'palevioletred': '#d87093',
    'papayawhip': '#ffefd5',
    'peachpuff': '#ffdab9',
    'peru': '#cd853f',
    'pink': '#ffc0cb',
    'plum': '#dda0dd',
    'powderblue': '#b0e0e6',
    'purple': '#800080',
    'red': '#ff0000',
    'rosybrown': '#bc8f8f',
    'royalblue': '#4169e1',
    'saddlebrown': '#8b4513',
    'salmon': '#fa8072',
    'sandybrown': '#f4a460',
    'seagreen': '#2e8b57',
    'seashell': '#fff5ee',
    'sienna': '#a0522d',
    'silver': '#c0c0c0',
    'skyblue': '#87ceeb',
    'slateblue': '#6a5acd',
    'slategray': '#708090',
    'slategrey': '#708090',
    'snow': '#fffafa',
    'springgreen': '#00ff7f',
    'steelblue': '#4682b4',
    'tan': '#d2b48c',
    'teal': '#008080',
    'thistle': '#d8bfd8',
    'tomato': '#ff6347',
    'turquoise': '#40e0d0',
    'violet': '#ee82ee',
    'wheat': '#f5deb3',
    'white': '#ffffff',
    'whitesmoke': '#f5f5f5',
    'yellow': '#ffff00',
    'yellowgreen': '#9acd32'
}